package com.seres.backend.admin;

import java.util.List;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;

public class GameParametersParser {
	private static final int DEMP_PARAM_COL_NR = 2;
	private static final int DEMP_PARAM_ROW_NR = 2;

	private static final int MULTIPLY_FACTOR_COL_NR = 2;
	private static final int MULTIPLY_FACTOR_ROW_NR = 3;
	
	private static final int AVG_SUST_COL_NR = 2;
	private static final int AVG_SUST_ROW_NR = 6;
	
	private static final int DECAY_FACTOR_COL_NR = 2;
	private static final int DECAY_FACTOR_ROW_NR = 7;
	
	private static final int DELAYED_IMPACT_COL_NR = 2;
	private static final int DELAYED_IMPACT_ROW_NR = 8;	
	
	private static final int MEMORY_LOSS_COL_NR = 2;
	private static final int MEMORY_LOSS_ROW_NR = 9;
	
	private static final int NR_OF_PAST_DECISIONS_COL_NR = 2;//# of player decisions back into the past
	private static final int NR_OF_PAST_DECISIONS_ROW_NR = 10; 
	
	private static final int RESCALE_MIN_COL_NR = 2;
	private static final int RESCALE_MIN_ROW_NR = 13;
	
	private static final int RESCALE_MAX_COL_NR = 2;
	private static final int RESCALE_MAX_ROW_NR = 14;
	
	private static final int MAX_NR_OF_ACES_COL_NR = 2;
	private static final int MAX_NR_OF_ACES_ROW_NR = 17;	
	
	private static final int TITLE_COL_NR = 1;
	private static final int TITLE_ROW_NR = 16;
	private static final String TITLE = "game parameters";
	
	private XSSFSheet worksheet;
	
	public GameParametersParser(XSSFSheet worksheet){
		setWorksheet(worksheet);
	}
	public GameParametersParserResult parse(){
		float dempParam = parseDempParameter(getWorksheet().getRow(DEMP_PARAM_ROW_NR).getCell(DEMP_PARAM_COL_NR));
		float multiplyFactor = parseMultiplyFactor(getWorksheet().getRow(MULTIPLY_FACTOR_ROW_NR).getCell(MULTIPLY_FACTOR_COL_NR));
		float avgSust = parseAverageSustainability(getWorksheet().getRow(AVG_SUST_ROW_NR).getCell(AVG_SUST_COL_NR));
		float decayFactor = parseDecayFactor(getWorksheet().getRow(DECAY_FACTOR_ROW_NR).getCell(DECAY_FACTOR_COL_NR));
		int delayedImpact = parseDelayedImpact(getWorksheet().getRow(DELAYED_IMPACT_ROW_NR).getCell(DELAYED_IMPACT_COL_NR));
		float memoryLoss = parseMemoryLoss(getWorksheet().getRow(MEMORY_LOSS_ROW_NR).getCell(MEMORY_LOSS_COL_NR));
		int nrOfPastDecisions = parseNumberOfPastDecisions(getWorksheet().getRow(NR_OF_PAST_DECISIONS_ROW_NR).getCell(NR_OF_PAST_DECISIONS_COL_NR));
		int rescaleMin = parseRescaleLimit(getWorksheet().getRow(RESCALE_MIN_ROW_NR).getCell(RESCALE_MIN_COL_NR));
		int rescaleMax = parseRescaleLimit(getWorksheet().getRow(RESCALE_MAX_ROW_NR).getCell(RESCALE_MAX_COL_NR));
		int maxNrOfAces = parseMaxNrOfAces(getWorksheet().getRow(MAX_NR_OF_ACES_ROW_NR).getCell(MAX_NR_OF_ACES_COL_NR));
		System.out.println("dempParam: " + dempParam);
		System.out.println("multiplyFactor: " + multiplyFactor);
		System.out.println("avgSust: " + avgSust);
		System.out.println("decayFactor: " + decayFactor);
		System.out.println("delayedImpact: " + delayedImpact);
		System.out.println("memoryLoss: " + memoryLoss);
		System.out.println("nrOfPastDecisions: " + nrOfPastDecisions);
		System.out.println("rescaleMin: " + rescaleMin);
		System.out.println("rescaleMax: " + rescaleMax);
		System.out.println("maxNrOfAces: " + maxNrOfAces);
		
		return new GameParametersParserResult(dempParam, multiplyFactor, avgSust, decayFactor, delayedImpact, memoryLoss, nrOfPastDecisions, rescaleMin, rescaleMax, maxNrOfAces);
	}

	private float parseDempParameter(XSSFCell cell) {
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (float) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid demp parameter cell");
		}
	}
	private float parseMultiplyFactor(XSSFCell cell) {
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (float) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid multiply factor cell");
		}
	}
	private float parseAverageSustainability(XSSFCell cell) {
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (float) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid avg sustainability cell");
		}
	}
	private float parseDecayFactor(XSSFCell cell) {
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (float) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid decay factor cell");
		}
	}

	private int parseDelayedImpact(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			int indicator = (int) cell.getNumericCellValue();			
			if(indicator == 0 || indicator == 1){
				return indicator;
			}
			else{
				throw new IllegalArgumentException("indicator field does not contain a boolean value");
			}
		}
		else{
			throw new IllegalArgumentException("invalid delayed impact cell");
		}
	}


	private float parseMemoryLoss(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (float) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid memory loss cell");
		}
	}
	private int parseNumberOfPastDecisions(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid nr of past decisions cell");
		}
	}	
	private int parseMaxNrOfAces(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid max nr of aces cell");
		}
	}
	private int parseRescaleLimit(XSSFCell cell){
		if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
			return (int) cell.getNumericCellValue();
		}
		else{
			throw new IllegalArgumentException("invalid rescale limit cell");
		}
	}
	private XSSFSheet getWorksheet() {
		return worksheet;
	}
	public boolean canHaveAsWorksheet(XSSFSheet worksheet){
		return worksheet.getRow(TITLE_ROW_NR).getCell(TITLE_COL_NR).getStringCellValue().toLowerCase().equals(TITLE);
	}
	public boolean canHaveAsModuleType(List<String> allowedModuleTypes, String type){
		for(String allowedModuleType : allowedModuleTypes){
			if(allowedModuleType.equals(type)){
				return true;
			}
		}
		return false;
	}
	private void setWorksheet(XSSFSheet worksheet) {
		if(canHaveAsWorksheet(worksheet)){
			this.worksheet = worksheet;
		}
		else{
			throw new IllegalArgumentException("invalid modules worksheet");
		}
		
	}
}
